package com.lottery.htbc.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.TreeSet;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.lottery.htbc.dao.BetAnalysisDao;
import com.lottery.htbc.dao.BetConfigDao;
import com.lottery.htbc.dao.BetRecordDao;
import com.lottery.htbc.dao.BetTaskDao;
import com.lottery.htbc.dao.ProfitAnalysisDao;
import com.lottery.htbc.dao.SynchroRecordDao;
import com.lottery.htbc.dao.UserAccountDao;
import com.lottery.htbc.dao.UserDao;
import com.lottery.htbc.dto.BetConfigDto;
import com.lottery.htbc.dto.ConfigTaskDto;
import com.lottery.htbc.dto.SynRecordDto;
import com.lottery.htbc.pojo.BetAnalysis;
import com.lottery.htbc.pojo.BetConfig;
import com.lottery.htbc.pojo.BetRecord;
import com.lottery.htbc.pojo.BetTask;
import com.lottery.htbc.pojo.SynRecord;
import com.lottery.htbc.pojo.UserAccount;
import com.lottery.htbc.thread.LuckDrawBase;
import com.lottery.htbc.utils.DateTimeConstant;
import com.lottery.htbc.utils.DateUtils;
import com.lottery.htbc.utils.FastJsonUtils;
import com.lottery.htbc.utils.StringUtils;
import com.lottery.htbc.utils.service.redis.RedisService;

/**
 * 急速pk10
 * 
 */
@Service
@SuppressWarnings("rawtypes")
public class JspkServiceImpl {


	private final static Logger LOGGER = LoggerFactory.getLogger(JspkServiceImpl.class);
	/**
	 * 一天对应的小数数
	 */
	private final static int  DAY_HOUR = 24;
	/**
	 * 避免多个服务同时跑的时候生成的任务不一致，过期时间为10分钟
	 */
	private final static int  TASK_TEMP_TIME =60*10;


	@Autowired
	private BetTaskDao betTaskDao;

	@Autowired
	private BetConfigDao betConfigDao;

	@Autowired
	private SynchroRecordDao synchroRecordDao;

	@Autowired
	private ProfitAnalysisDao  profitAnalysisDao;

	@Autowired
	private BetRecordDao  betRecordDao;

	@Autowired
	private UserAccountDao  userAccountDao;

	@Autowired
	private UserDao  userDao;

	@Autowired
	private BetAnalysisDao  betAnalysisDao;


	/**
	 * redis 操作对象
	 * 
	 */
	@Autowired
	protected RedisService redisService;

	public void planBetTask(){
		//重建表
		betTaskDao.truncateTable();
		LOGGER.info("清除昨天的计划成功");
		String taskDataRedisye="Task_Temp";
		try {
			String taskData=redisService.get(taskDataRedisye);
			if(taskData!=null){
				List<BetTask> betTasks=FastJsonUtils.toList(taskData, BetTask.class);
				LOGGER.info("缓存中获取任务策略");
				betTaskDao.saveBatch(betTasks);
				return;
			}
		} catch (Exception e) {
			LOGGER.info("缓存中获取任务策略失败 {}",e.getMessage());
			e.printStackTrace();
		}
		List<BetConfig> configs=betConfigDao.queryAll();
		if(configs!=null&&configs.size()>0){
			List<BetTask> betTasks=new ArrayList<BetTask>();
			Random rd=new Random();
			for(BetConfig config:configs){
				String userIdStr =StringUtils.changeNumToStr(config.getUserId(),7);
				Set<Integer> hourList=new TreeSet<>();
				do {
					// 8到22的随机数(0~14)+8
					Integer hour=rd.nextInt(DAY_HOUR-10)+8;
					Integer repeatHour=hour-1;
					if(!hourList.contains(repeatHour)){
						hourList.add(hour) ;
					}
				}while (hourList.size()<config.getDayFrequency());
				for(Integer hour:hourList){
					BetTask task=new BetTask();
					task.setConfigId(config.getId());
					task.setHour(hour);
					task.setTaskId("TASK-"+DateUtils.getDays()+"-"+StringUtils.getRandomUUID().substring(0,16).toUpperCase()+userIdStr+"-"+(hour>9?hour:"0"+hour));
					betTasks.add(task);
				}
			}
			try {
				redisService.set(taskDataRedisye, FastJsonUtils.toJSONString(betTasks),TASK_TEMP_TIME);
				LOGGER.info("任务策略写入缓存");
			} catch (Exception e) {
				LOGGER.info("任务策略写入缓存失败 {}",e.getMessage());
				e.printStackTrace();
			}
			betTaskDao.saveBatch(betTasks);
		}
	}

	/**
	 * 根据任务时间(小时) 获取用户配置<br/>
	 * @param hour
	 * @return
	 */
	public List<ConfigTaskDto> queryByTaskHour(Integer hour){
		return betConfigDao.queryByTaskHour(hour);
	}


	public List<BetConfig> queryValidUserConfigAll(){
		return betConfigDao.queryValidAll();
	}

	/**
	 * 同步盈利
	 * @throws Exception 
	 */

	public void synProfit() throws Exception{
		//查询未统计的
		LOGGER.info("开始查询和统计上一期的中奖状态");
		List<SynRecord> syns=synchroRecordDao.queryNotSyn();
		if(syns!=null&&syns.size()>0){
			LuckDrawBase luckDraw=new LuckDrawBase(46);
			luckDraw.setRedisService(redisService);
			List<SynRecordDto> synDtos=new ArrayList<SynRecordDto>();
			for(SynRecord syn:syns){
				Map recordMap=	luckDraw.queryRecord(syn.getSynToken());
				SynRecordDto synDto=new SynRecordDto();
				BetConfigDto betConfig=new BetConfigDto();
				betConfig.setUserId(syn.getUserId());
				synDto.setId(syn.getId());
				try {
					BetRecord betRecord=gainBeforeRecord(recordMap);
					betRecord.setUserId(syn.getUserId());
					if(betRecord!=null){
						Boolean isFlyback=false;
						if(syn.getRoundId().equals(betRecord.getRoundId())&&syn.getRoundNo().equals(betRecord.getRoundNo())){
							String continuousStr="0";
							String rediey="HTBC_"+DateUtils.getDays()+"_"+syn.getAccount();
							if(betRecord.getWinAmount()!=null&&Float.valueOf(betRecord.getWinAmount())>0){
								luckDraw.winnerAnalysis(true, syn.getAccount());
								isFlyback=luckDraw.calculationBei(true, syn.getAccount());
								String hitContinueKey=rediey+"_hit_continue";
								continuousStr=redisService.get(hitContinueKey);
							}
							else{
								luckDraw.winnerAnalysis(false, syn.getAccount());
								isFlyback=luckDraw.calculationBei(false, syn.getAccount());
								String missContinueKey=rediey+"_miss_continue";
								continuousStr=redisService.get(missContinueKey);
							}
							betConfig.setIsFlyback(isFlyback);
							if(continuousStr!=null){
								betRecord.setContinuous(Integer.valueOf(continuousStr));
							}
							BetTask task=new BetTask();
							task.setTaskId(syn.getTaskId());
							if(betRecord.getBetAmount()!=null){
								task.setThrowAmount(Float.valueOf(betRecord.getBetAmount()));
								synDto.setThrowAmount(Float.valueOf(betRecord.getBetAmount()));
							}
							if(betRecord.getWinAmount()!=null){
								task.setWinAmount(Float.valueOf(betRecord.getWinAmount()));
								synDto.setWinAmount(Float.valueOf(betRecord.getWinAmount()));
							}
							betConfigDao.updateByIsFlyback(betConfig);
							synDto.setBetRecord(betRecord);
							synDto.setBetTask(task);
						}
					}
				} catch (Exception e) {
					LOGGER.info("统计上一期的中奖状态出错>>>>>>账户:{},异常信息:{}",synDto.getAccount(),e.getMessage());
					e.printStackTrace();
				}
				synDtos.add(synDto);
			}
			synchroRecordDao.syncFinish(synDtos);
			LOGGER.info("统计上一期的中奖状态完成 总共统计{} 条",synDtos.size());
		}
		else{
			LOGGER.info("上一期的没有待同步统计的记录");
		}
	}



	/**
	 * 
	 * @param recordMap
	 * @throws Exception
	 */
	private  BetRecord  gainBeforeRecord(Map recordMap)throws Exception{
		List<Map> itemMap= FastJsonUtils.toList(recordMap.get("items").toString(),Map.class);
		if(itemMap!=null&&itemMap.size()>0){
			Map map=  itemMap.get(0);
			return structureRecord(map);
		}
		return null;
	}


	private  BetRecord structureRecord(Map item){
		if(item!=null){
			BetRecord record=new BetRecord();
			record.setResult(FastJsonUtils.mapToJSONString(item));
			if(item.get("round_no")!=null){
				record.setRoundNo(item.get("round_no").toString());
			}
			if(item.get("order_no")!=null){
				record.setOrderNo(item.get("order_no").toString());
			}
			if(item.get("extra_cmd")!=null){
				record.setExtraCmd(item.get("extra_cmd").toString());
			}
			if(item.get("p")!=null){
				record.setP(item.get("p").toString());
			}
			if(item.get("game_name")!=null){
				record.setGameName(item.get("game_name").toString());
			}
			if(item.get("round_id")!=null){
				record.setRoundId(item.get("round_id").toString());
			}
			if(item.get("amount")!=null){
				record.setBetAmount(item.get("amount").toString());
			}
			if(item.get("win_amount")!=null){
				record.setWinAmount(item.get("win_amount").toString());
			}
			if(item.get("time")!=null){
				Long time=Long.valueOf(item.get("time").toString()+"000");
				record.setBetTime(DateUtils.formatDateFull(new Date(time)));
			}
			if(item.get("offc_vars")!=null){
				String offcVars=item.get("offc_vars").toString();
				record.setBetVars(offcVars);
				Map varsMap=FastJsonUtils.stringToMap(offcVars);
				if(varsMap!=null){
					if(varsMap.get("bei")!=null){
						record.setBei(Integer.valueOf(varsMap.get("bei").toString()));
					}
					if(varsMap.get("mode")!=null){
						record.setMode(varsMap.get("mode").toString());
					}
					if(varsMap.get("zhu")!=null){
						record.setZhu(Integer.valueOf(varsMap.get("zhu").toString()));
					}
					if(varsMap.get("wins")!=null){
						record.setWins(varsMap.get("wins").toString());
					}
					if(varsMap.get("balls")!=null){
						record.setBetValue(varsMap.get("balls").toString());
					}

				}
			}
			return record;
		}
		return null;

	}


	/**
	 * 通过任务汇总盈利
	 */
	public void  summaryProfitByTask(){
		profitAnalysisDao.profitAnalysisByTask();
	}

	/**
	 * 备份同步记录和投注记录的月度数据
	 */
	public void backupsTableDataByMonth() {
		//获取一周前的年月
		String ym=DateUtils.getMonth2(new Date(System.currentTimeMillis()-DateTimeConstant.WEEK));
		synchroRecordDao.backupsTableDataByMonth(ym);
		LOGGER.info("备份同步记录表成功");
		betRecordDao.backupsTableDataByMonth(ym);
		LOGGER.info("备份投注记录表成功");

	}


	public void synBalanceValid() {
		List<UserAccount> accounts=userAccountDao.queryAllValid();
		if(accounts!=null&&accounts.size()>0){
			LuckDrawBase lucky=new LuckDrawBase();
			for(UserAccount account:accounts){
				try {
					Map balanceMap=	lucky.synBalance(account.getSynToken());
					if(balanceMap!=null){
						account.setSynResult(FastJsonUtils.mapToJSONString(balanceMap));
						if(balanceMap.get("amount")!=null){
							Float balance=Float.valueOf(balanceMap.get("amount").toString());
							account.setBalance(balance/100);
						}
					}
				} catch (Exception e) {
					LOGGER.info("账户:{},同步余额失败:{}",account.getAccount(),e.getMessage());
					e.printStackTrace();
				}

			}
			userAccountDao.synBatch(accounts);
			LOGGER.info("同步用户余额,总共统计{}条",accounts.size());
		}

	}

	public void winnerAnalysis() {
		List<BetConfig> ubcs=betConfigDao.queryByInfo(new BetConfig());
		if(ubcs!=null&&ubcs.size()>0){
			List<BetAnalysis> analysis=new ArrayList<BetAnalysis>();
			for(BetConfig ubc:ubcs){
				if(ubc.getAccount()!=null&&ubc.getAccount().length()>0){
					String day=DateUtils.getDays();
					BetAnalysis hit=new BetAnalysis();
					hit.setDay(day);
					hit.setUserId(ubc.getId());
					hit.setAccount(ubc.getAccount());
					hit.setDayFrequency(ubc.getDayFrequency());
					hit.setType("HIT");
					BetAnalysis miss=new BetAnalysis();
					miss.setDay(day);
					miss.setUserId(ubc.getId());
					miss.setAccount(ubc.getAccount());
					miss.setType("MISS");
					miss.setDayFrequency(ubc.getDayFrequency());
					String rediey="HTBC_"+day+"_"+ubc.getAccount();
					String hiTotalKey=rediey+"_hit_total";
					String hitMaxKey=rediey+"_hit_max";
					String flowRedisKey="HTBC_BS_INDEX_FLOW_"+day+"_"+ubc.getAccount();
					String flowStr=redisService.get(flowRedisKey);
					hit.setIndexFlow(flowStr);
					miss.setIndexFlow(flowStr);
					redisService.del(flowRedisKey);
					//总记录次数
					String hiTotalStr=redisService.get(hiTotalKey);
					if(hiTotalStr!=null){
						hit.setTotal(Integer.valueOf(hiTotalStr));
						redisService.del(hiTotalKey);
					}
					//最大次数
					String hitMaxStr=redisService.get(hitMaxKey);
					if(hitMaxStr!=null){
						hit.setMax(Integer.valueOf(hitMaxStr));
						redisService.del(hitMaxKey);
					}
					gradeAnalysis(hit,"hit");
					if(hit.getTotal()!=null){
						analysis.add(hit);
					}
					String missTotalKey=rediey+"_miss_total";
					String missMaxKey=rediey+"_miss_max";
					//总记录次数
					String missTotal=redisService.get(missTotalKey);
					if(missTotal!=null){
						miss.setTotal(Integer.valueOf(missTotal));
						redisService.del(missTotalKey);
					}
					//最大次数
					String missMaxStr=redisService.get(missMaxKey);
					if(missMaxStr!=null){
						miss.setMax(Integer.valueOf(missMaxStr));
						redisService.del(missMaxKey);
					}
					gradeAnalysis(miss,"miss");
					redisService.del(rediey+"_hit_continue");
					redisService.del(rediey+"_miss_continue");
					if(miss.getTotal()!=null){
						analysis.add(miss);
					}
					String indexCurrentRedisKey="HTBC_BS_INDEX_CURRENT_"+ubc.getAccount();
					String indexCurrentStr=redisService.get(indexCurrentRedisKey);
					if(indexCurrentStr!=null){
						Integer indexCurrent=Integer.valueOf(indexCurrentStr);
						if(indexCurrent<10){
							redisService.del(indexCurrentRedisKey);
						}
					}
				}
			}
			betAnalysisDao.saveBatch(analysis);
		}
	}

	private void gradeAnalysis(BetAnalysis grade,String type){
		String rediey="HTBC_"+DateUtils.getDays()+"_"+grade.getAccount();
		String gradeKey=rediey+"_"+type+"_grade_";
		String gradeTwo=redisService.get(gradeKey+"2");
		if(gradeTwo!=null){
			grade.setGradeTwo(Integer.valueOf(gradeTwo));
			redisService.del(gradeKey+"2");
		}
		String gradeThree=redisService.get(gradeKey+"3");
		if(gradeThree!=null){
			grade.setGradeThree(Integer.valueOf(gradeThree));
			redisService.del(gradeKey+"3");
		}
		String gradeFour=redisService.get(gradeKey+"4");
		if(gradeFour!=null){
			grade.setGradeFour(Integer.valueOf(gradeFour));
			redisService.del(gradeKey+"4");
		}
		String gradeFive=redisService.get(gradeKey+"5");
		if(gradeFive!=null){
			grade.setGradeFive(Integer.valueOf(gradeFive));
			redisService.del(gradeKey+"5");
		}
		String gradeSex=redisService.get(gradeKey+"6");
		if(gradeSex!=null){
			grade.setGradeSex(Integer.valueOf(gradeSex));
			redisService.del(gradeKey+"6");
		}
		String gradeSeven=redisService.get(gradeKey+"7");
		if(gradeSeven!=null){
			grade.setGradeSeven(Integer.valueOf(gradeSeven));
			redisService.del(gradeKey+"7");
		}
		String gradeEight=redisService.get(gradeKey+"8");
		if(gradeEight!=null){
			grade.setGradeEight(Integer.valueOf(gradeEight));
			redisService.del(gradeKey+"8");
		}
		String gradeNine=redisService.get(gradeKey+"9");
		if(gradeNine!=null){
			grade.setGradeNine(Integer.valueOf(gradeNine));
			redisService.del(gradeKey+"9");
		}
		String gradeTen=redisService.get(gradeKey+"10");
		if(gradeTen!=null){
			grade.setGradeTen(Integer.valueOf(gradeTen));
			redisService.del(gradeKey+"10");
		}
		LOGGER.info("删除等级[ gradeKey={} ]成功",gradeKey);
		String gradeTenAbove="";
		for(int i=11;i<20;i++){
			String gradeTenLarge=redisService.get(gradeKey+i);
			if(gradeTenLarge!=null){
				gradeTenAbove+="连续"+i+"次"+type+"的次数是:"+gradeTenLarge+",";
				redisService.del(gradeKey+i);
				LOGGER.info("删除等级[ gradeKey={} ]成功",gradeKey+i);
			}
			else{
				break;
			}
		}
		grade.setGradeTenAbove(gradeTenAbove);
	}

}
